/*
@hehung
2023-7-15
email: 1398660197@qq.com
wechat: hehung95
reproduced and please indicate the source @hehung
*/

// MQ5 - 可燃气体传感器，用来检测可燃气体，使用的是ADC获取空气中可燃气体浓度
// P000 ADC0 CH0
/*
P001 - AN001 : Joystick X
P002 - AN002 : Joystick Y
P003 - AN003 : MQ5
*/

#include "app_common.h"


#define MQ5_DEBUG
#define JOYSTICK_DEBUG

#undef JOYSTICK_DEBUG
#undef MQ5_DEBUG

#ifdef MQ5_DEBUG
#include <stdio.h>
#define MQ5_LOG(fmt, ...) 	          printf(fmt, ##__VA_ARGS__)
#else
#define MQ5_LOG(fmt, ...)
#endif

#ifdef JOYSTICK_DEBUG
#include <stdio.h>
#define JOYSTICK_LOG(fmt, ...) 	          printf(fmt, ##__VA_ARGS__)
#else
#define JOYSTICK_LOG(fmt, ...)
#endif


// adc sampling resoultion is 12bits
#define MQ5_ADC_RESOLUTION            (12U)
#define MQ5_ADC_MAX_VALUE             (4095)
#define MQ5_ADC_SAMPLE_NUM            (1)

#define MQ5_MAX_VALUE                 (10000U)   //ppm
#define MQ5_MIN_VALUE                 (300U)     //ppm

#define ADC_JOYSTICK_X_CHANNEL        (1U)
#define ADC_JOYSTICK_Y_CHANNEL        (2U)
#define ADC_JOYSTICK_Z_CHANNEL        (10U)
#define ADC_MQ5_CHANNEL               (3U)

#define JOYSTICK_BUTTON               (BSP_IO_PORT_00_PIN_10)   // P010
#define JOYSTICK_UP_THD               (3100U)
#define JOYSTICK_DOWN_THD             (900U)


// Value for Combustible gas concentration
static uint32_t mq5_val_ppm = 0U;
// Value for Rcoker
static s_joystick_t joystick_val;
static e_joystick_cmd_t joystick_cmd = JOYSTICK_NONE;


static void Mq5_DataConvert(uint16_t adc_data);
static void Joystick_CmdJudge(void);

/*************************************************************************************************/
/************************************** MQ5 ******************************************************/
/*************************************************************************************************/
// Convert the ADC value to percent value
static void Mq5_DataConvert(uint16_t adc_data)
{
    // calculate the Combustible gas simple in ppm, it is not an accurate actual value
    // y = kx+b, x = 0, y = 300, x = 4095, y = 10000, so k = (10000-300)/4095
    mq5_val_ppm = ((MQ5_MAX_VALUE - MQ5_MIN_VALUE) / MQ5_ADC_MAX_VALUE) * adc_data;
}

// get the value and the unit is ppm
uint32_t Mq5_GetGasPpmValue(void)
{
    return mq5_val_ppm;
}

// Read conversion result 
void Mq5_RunningEntry(void)
{	
	fsp_err_t err = FSP_SUCCESS;
	uint16_t adc_value;
	uint8_t read_cnt = 0;
	uint32_t adc_value_sum = 0;
	
	err = R_ADC_Read(&g_adc0_ctrl, ADC_MQ5_CHANNEL, &adc_value);
    if (FSP_SUCCESS == err)
	{
        MQ5_LOG ("Mq5: Read value: %d: %d\r\n", ADC_MQ5_CHANNEL, adc_value);
		adc_value_sum += (uint32_t)adc_value;
		
		if (read_cnt == MQ5_ADC_SAMPLE_NUM)
		{
			adc_value = (uint16_t)(adc_value_sum / MQ5_ADC_SAMPLE_NUM);
		}
		else 
		{
			read_cnt ++;
			adc_value = (uint16_t)(adc_value_sum / read_cnt);
		}
		Mq5_DataConvert(adc_value);
    }
    else
    {
        MQ5_LOG ("MQ5: Read MQ5 Data Error\r\n");
    }
}

/*************************************************************************************************/
/************************************** Joystick *************************************************/
/*************************************************************************************************/

static void Joystick_CmdJudge(void)
{
	joystick_cmd = JOYSTICK_NONE;
	
	if (joystick_val.x > JOYSTICK_UP_THD)
	{
		joystick_cmd = JOYSTICK_RIGHT;
	}
	else if (joystick_val.x < JOYSTICK_DOWN_THD)
	{
		joystick_cmd = JOYSTICK_LEFT;
	}
	else if (joystick_val.y > JOYSTICK_UP_THD)
	{
		joystick_cmd = JOYSTICK_DOWN;
	}
	else if (joystick_val.y < JOYSTICK_DOWN_THD)
	{
		joystick_cmd = JOYSTICK_UP;
	}
	else if (joystick_val.z < 500U)
	{
		joystick_cmd = JOYSTICK_PRESSED;
	}
	
	JOYSTICK_LOG ("Joystick command is %d\r\n", joystick_cmd);
}

// Read conversion result 
void Joystick_RunningEntry(void)
{	
	fsp_err_t err = FSP_SUCCESS;
	uint16_t adc_value;
	
	err = R_ADC_Read(&g_adc0_ctrl, ADC_JOYSTICK_X_CHANNEL, &adc_value);

    if (FSP_SUCCESS == err)
	{
		joystick_val.x = adc_value;
        JOYSTICK_LOG ("Joystick: Read X value: %d: %d\r\n", ADC_JOYSTICK_X_CHANNEL, adc_value);
    }
    else
    {
        JOYSTICK_LOG ("Joystick: Read Joystick X Data Error\r\n");
    }
	
	err = R_ADC_Read(&g_adc0_ctrl, ADC_JOYSTICK_Y_CHANNEL, &adc_value);

	if (FSP_SUCCESS == err)
	{
		joystick_val.y = adc_value;
        JOYSTICK_LOG ("Joystick: Read Y value: %d: %d\r\n", ADC_JOYSTICK_Y_CHANNEL, adc_value);
    }
    else
    {
        JOYSTICK_LOG ("Joystick: Read Z Joystick Y Data Error\r\n");
    }
	
	err = R_ADC_Read(&g_adc0_ctrl, ADC_JOYSTICK_Z_CHANNEL, &adc_value);

	if (FSP_SUCCESS == err)
	{
		joystick_val.z = adc_value;
        JOYSTICK_LOG ("Joystick: Read Z value: %d: %d\r\n", ADC_JOYSTICK_Z_CHANNEL, adc_value);
    }
    else
    {
        JOYSTICK_LOG ("Joystick: Read Joystick Z Data Error\r\n");
    }
	
	Joystick_CmdJudge();
}


e_joystick_cmd_t Joystick_GetCmd(void)
{
	return joystick_cmd;
}


/*************************************************************************************************/
/************************************** ADC ******************************************************/
/*************************************************************************************************/
// Initialize the MQ5 - ADC0 CH0 P000
void Adc_Init(void)
{
    fsp_err_t err = FSP_SUCCESS;
	
    /* Initializes the adc. */
    err = R_ADC_Open(&g_adc0_ctrl, &g_adc0_cfg);
	/* Handle any errors. This function should be defined by the user. */
    assert(FSP_SUCCESS == err);
    /* Enable channels. */
    err = R_ADC_ScanCfg(&g_adc0_ctrl, &g_adc0_channel_cfg);
    assert(FSP_SUCCESS == err);

    /* Enable scan triggering from ELC events. */
    (void)R_ADC_ScanStart(&g_adc0_ctrl);
}
